package cn.unknowpupil.service.system.impl;

import cn.unknowpupil.common.core.exceptions.HealthException;
import cn.unknowpupil.common.core.utils.StringUtils;
import cn.unknowpupil.domain.system.SysRole;
import cn.unknowpupil.domain.system.SysUser;
import cn.unknowpupil.mapper.system.SysRoleMapper;
import cn.unknowpupil.service.system.ISysMenuService;
import cn.unknowpupil.service.system.ISysRoleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created at 2020-10-21 by  w10g <br>
 * Initialize SysRole  ... <br>
 * 角色信息表 核心业务处理实现类
 *
 * @author unknowpupil
 * @since 0.0.1
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    @Resource
    private ISysMenuService sysMenuService;


    /**
     * 新增
     *
     * @param sysRole {@link SysRole}  角色信息表
     * @return {@link SysRole}
     */
    @Override
    public boolean create(SysRole sysRole) {
        boolean b = checkRoleNameUnique(sysRole);
        if (!b) {
            throw new HealthException("新增角色'" + sysRole.getRoleName() + "'失败，角色名称已存在");
        }
        b = checkRoleKeyUnique(sysRole);
        if (!b) {
            throw new HealthException("新增角色'" + sysRole.getRoleName() + "'失败，角色权限已存在");
        }
        // 新增角色信息
        save(sysRole);
        //新增角色菜单信息
        int i = baseMapper.insertRoleMenuRelatedness(sysRole.getMenuIds(), sysRole.getId());
        if(i>0){
            return true;
        }else {
            throw new HealthException("新增角色菜单信息失败");
        }

    }



    /**
     * 校验角色权限是否唯一
     *
     * @param role 角色信息
     * @return 结果 唯一true 不唯一false
     */
    public boolean checkRoleKeyUnique(SysRole role) {
        Long roleId = StringUtils.isNull(role.getId()) ? -1L : role.getId();
        SysRole info = baseMapper.selectOne(new LambdaQueryWrapper<SysRole>().eq(SysRole::getRoleKey, role.getRoleKey()));
        if (StringUtils.isNotNull(info) && info.getId().longValue() != roleId.longValue()) {
            return false;
        }
        return true;
    }

    /**
     * 校验角色名称是否唯一
     *
     * @param role 角色信息
     * @return 结果 唯一true 不唯一false
     */
    public boolean checkRoleNameUnique(SysRole role) {
        Long roleId = StringUtils.isNull(role.getId()) ? -1L : role.getId();
        SysRole info = baseMapper.selectOne(new LambdaQueryWrapper<SysRole>().eq(SysRole::getRoleName, role.getRoleName()));
        if (StringUtils.isNotNull(info) && info.getId().longValue() != roleId.longValue()) {
            return false;
        }
        return true;
    }

    /**
     * 详情
     *
     * @param id {@code Long}   SysRole ID
     * @return {@link SysRole}
     */
    @Override
    public SysRole info(Long id) {
        return getById(id);
    }

    /**
     * 删除
     *
     * @param ids {@code Long}   SysRole ID
     * @return {@link SysRole}
     */
    @Override
    public boolean delete(Long[] ids) {
        for (Long id : ids) {
            checkRoleAllowed(new SysRole(id));
            SysRole role = getById(id);

            if (baseMapper.countUserRoleByRoleId(id) > 0) {
                throw new HealthException(String.format("%1$s已分配,不能删除", role.getRoleName()));
            }
        }

        List<Long> collect = Stream.of(ids).collect(Collectors.toList());
        return removeByIds(collect);
    }


    /**
     * 修改
     *
     * @param sysRole {@link SysRole}  角色信息表
     * @return {@link SysRole}
     */
    @Override
    public boolean update(SysRole sysRole) {
        boolean b = checkRoleNameUnique(sysRole);
        if (!b) {
            throw new HealthException("新增角色'" + sysRole.getRoleName() + "'失败，角色名称已存在");
        }
        b = checkRoleKeyUnique(sysRole);
        if (!b) {
            throw new HealthException("新增角色'" + sysRole.getRoleName() + "'失败，角色权限已存在");
        }
        // 修改角色信息
        updateById(sysRole);
        // 删除角色与菜单关联

        baseMapper.deleteRoleMenuRelatednessByRoleId(sysRole.getId());
        //新增角色菜单信息
        int i = baseMapper.insertRoleMenuRelatedness(sysRole.getMenuIds(), sysRole.getId());
        if(i>0){
            return true;
        }else {
            throw new HealthException("新增角色菜单信息失败");
        }

    }


    /**
     * 分页
     *
     * @param current {@code int} 页码
     * @param size    {@code int} 笔数
     * @param sysRole {@link SysRole}
     * @return {@code IPage<SysRole>}
     */
    @Override
    public IPage<SysRole> page(int current, int size, SysRole sysRole) {
        IPage<SysRole> page = new Page<>(current, size);
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(sysRole.getRoleKey())) {
            wrapper.like(SysRole::getRoleKey, sysRole.getRoleKey());
        }
        if (StringUtils.isNotBlank(sysRole.getStatus())) {
            wrapper.eq(SysRole::getStatus, sysRole.getStatus());
        }
        if (StringUtils.isNotBlank(sysRole.getRoleName())) {
            wrapper.like(SysRole::getRoleName, sysRole.getRoleName());
        }
        wrapper.orderByAsc(SysRole::getRoleSort);
        return super.page(page, wrapper);
    }

    @Override
    public Set<String> getRolePermission(SysUser user) {
        Set<String> roles = new HashSet<String>();
        // 管理员拥有所有权限
        if (user.isAdmin()) {
            roles.add("USER_ADMIN");
        } else {
            roles.addAll(selectRolePermissionByUserId(user.getId()));
        }
        return roles;
    }

    private Set<String> selectRolePermissionByUserId(Long id) {
        List<SysRole> perms = baseMapper.selectRolePermissionByUserId(id);
        Set<String> permsSet = new HashSet<>();
        for (SysRole perm : perms) {
            if (!Objects.isNull(perm)) {
                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
            }
        }
        return permsSet;
    }

    @Override
    public Set<String> getMenuPermission(SysUser user) {
        Set<String> perms = new HashSet<String>();
        // 管理员拥有所有权限
        if (user.isAdmin()) {
            perms.add("*:*:*");
        } else {
            perms.addAll(sysMenuService.selectMenuPermsByUserId(user.getId()));
        }
        return perms;
    }

    @Override
    public List<SysRole> selectRoleAll() {
        return super.list();
    }

    @Override
    public List<Long> selectRoleListByUserId(Long userId) {
        return baseMapper.selectRoleListByUserId(userId);
    }

    /**
     * 校验角色是否允许操作
     *
     * @param role 角色信息
     */
    @Override
    public void checkRoleAllowed(SysRole role) {
        if (StringUtils.isNotNull(role.getId()) && role.isAdmin()) {
            throw new HealthException("不允许操作超级管理员角色");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean authDataScope(SysRole role) {
        // 修改角色信息
        baseMapper.updateById(role);

        // 删除角色与部门关联
        baseMapper.deleteRoleDeptRelatednessByRoleId(role.getId());
        // 新增角色和部门信息（数据权限）

        int i = baseMapper.insertRoleDeptRelatednessByDeptId(role.getDeptIds(), role.getId());

        if(i>0){
            return true;
        }else {
            throw new HealthException("新增角色部门信息插入失败");
        }
    }




}
